/**
 * 接口监控
 */
import { ReportType } from './constant';
import { ReportParams } from './types';
import Utils from './utils';

// 使用 WeakMap 存储每个 XMLHttpRequest 实例的监控信息
const xhrInfoMap = new WeakMap<XMLHttpRequest, Partial<ReportParams>>();

export default class Xhr {
	constructor(private callback: (params: ReportParams) => void) {
		Utils.log('接口监控初始化成功');
		this.xhrHook();
	}

	xhrHook() {
		const xhrSelf = this;
		const xhrProto = XMLHttpRequest.prototype;
		const originalOpen = xhrProto.open;
		const originalSend = xhrProto.send;

		// 重写 open 方法
		xhrProto.open = function (method: string, url: string) {
			// 将初始信息存入 WeakMap
			xhrInfoMap.set(this, {
				url: url,
				method: method.toUpperCase(),
			});

			return originalOpen.apply(this, arguments as any);
		};

		// 重写 send 方法
		xhrProto.send = function (body?: Document | XMLHttpRequestBodyInit | null) {
			const xhr = this;
			const startTime = Date.now();

			// 从 WeakMap 获取初始信息
			const initialInfo = xhrInfoMap.get(xhr) || {};

			// 创建事件处理函数
			const handleEvent = (eventType: string) => () => {
				const info = xhrInfoMap.get(xhr) || initialInfo;

				// 更新监控信息
				const updatedInfo: Partial<ReportParams> = {
					...info,
					subType: eventType,
					status: xhr.status,
					success:
						(xhr.status >= 200 && xhr.status <= 206) || xhr.status === 304,
					duration: Date.now() - startTime,
					requestData: Utils.isFormData(body) ? 'FormData' : body,
				};

				// 处理响应数据
				if (xhr.response) {
					let responseSize = null;
					let responseData = null;

					switch (xhr.responseType) {
						case 'json':
							try {
								responseSize = JSON.stringify(xhr.response).length;
								responseData = JSON.stringify(xhr.response);
							} catch (error) {
								Utils.log('error', 'JSON stringify error:', error);
							}
							break;
						case 'blob':
							responseSize = (xhr.response as Blob).size;
							break;
						case 'arraybuffer':
							responseSize = (xhr.response as ArrayBuffer).byteLength;
							break;
						case 'document':
							if (xhr.response.documentElement) {
								responseSize =
									xhr.response.documentElement &&
									xhr.response.documentElement.innerHTML &&
									xhr.response.documentElement.innerHTML.length + 28;
							}

							break;
						default:
							try {
								if (typeof xhr.response === 'string') {
									responseSize = xhr.response.length;
									responseData = xhr.response;
								} else {
									responseSize = JSON.stringify(xhr.response).length;
									responseData = JSON.stringify(xhr.response);
								}
							} catch (error) {
								Utils.log('error', 'Response processing error:', error);
							}
					}

					updatedInfo.responseSize = responseSize;
					updatedInfo.responseData = responseData;
				}

				// 更新 WeakMap 中的信息
				xhrInfoMap.set(xhr, updatedInfo);

				// 触发回调
				xhrSelf.callback({
					...updatedInfo,
					type: ReportType.XHR,
					message: '接口监控',
				} as ReportParams);
			};

			// 添加事件监听
			const addEvent = (type: string) => {
				xhr.addEventListener(type, handleEvent(type));
			};

			if (xhr.addEventListener!) {
				addEvent('load');
				addEvent('error');
				addEvent('abort');
			} else {
				const originalStateChange = xhr.onreadystatechange;
				xhr.onreadystatechange = function () {
					originalStateChange?.apply(this, arguments as any);
					if (xhr.readyState === 4) {
						handleEvent('load')();
					}
				};
			}

			return originalSend.apply(xhr, arguments as any);
		};
	}
}
